home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
BCCAPP.ARJ
/
REPORT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-15
|
9KB
|
502 lines
/*
*
* Report creation
*
* (C) 1990 Vision Software
*
* $Id: report.c 1.2002 91/05/04 16:24:47 pcalvin beta $
*
* Comments:
*
* Generates trivial reports from a specific database.
* Non-trivial reports (i.e relations etc) are not yet supported.
*
* Bugs:
*
* None documented
*/
#include <string.h>
#include <stdhdr.h>
#include <adl.h>
#include <report.h>
#include "lowlevel.h"
/*
* Virtual Base class for report output. Right now, we may
* send reports to screen or printer.
*/
class OUTPUT
{
public:
OUTPUT(SZ szText,SZ szBar,PTL ptl,CCH cchMac);
VIRTUAL ~OUTPUT();
VIRTUAL VOID SendSz(SZ sz) = 0;
BOOL FContinue();
protected:
VOID Title();
VOID Terminate();
ROW crowMac;
ROW crowCurrent;
SZ szTitleText;
SZ szTitleBar;
PTL ptlFirst;
private:
CCH cchReportWidthMac;
BOOL fContinueReport;
};
/*
* Screen reports.
*/
class SCREEN_OUTPUT : public OUTPUT
{
public:
SCREEN_OUTPUT(SZ szText,SZ szBar,PTL ptl,CCH cchWidthMac,CTL ctl);
VIRTUAL ~SCREEN_OUTPUT();
VIRTUAL VOID SendSz(SZ sz);
private:
WINDOW wnd;
};
/*
* Printer reports.
*/
class PRINTER_OUTPUT : public OUTPUT
{
public:
PRINTER_OUTPUT(SZ szText,SZ szBar,PTL ptl,CCH cchWidthMac);
VIRTUAL ~PRINTER_OUTPUT();
VIRTUAL VOID SendSz(SZ sz);
};
/*
* Simple creation, we just need a database to start report from
*/
REPORT::REPORT(DATABASE &rdtbReport) : rdtb(rdtbReport)
{
penFirst = penNil;
penCurrent = penNil;
ptlFirst = ptlNil;
ptlCurrent = ptlNil;
ctlCurrent = ctlNil;
cchReportWidthMac = cchNil;
pfnFUsePdb = Nil;
}
REPORT::~REPORT()
{
PEN pen = penFirst;
PTL ptl = ptlFirst;
/*
* Simply unload all the entries..
*/
while (pen != penNil)
{
PEN penNext = pen->penNext;
delete pen;
pen = penNext;
}
/*
* And the titles..
*/
while (ptl != ptlNil)
{
PTL ptlNext = ptl->ptlNext;
delete ptl;
ptl = ptlNext;
}
}
/*
* Set filter for this report..
*/
VOID REPORT::SetFilterTo(BOOL (*pfnFUse)(DBASE *pdb))
{
pfnFUsePdb = pfnFUse;
}
/*
* Create a new title for this report
*/
VOID REPORT::Title(SZ sz,AL al)
{
PointerAssert(sz);
PTL ptl = new TL;
/*
* Create..
*/
ptl->ptlNext = ptlNil;
ptl->sz = sz;
ptl->al = al;
/*
* Now, link in with the current list..
*/
if (ptlFirst == ptlNil)
ptlFirst = ptl;
if (ptlCurrent != ptlNil)
ptlCurrent->ptlNext = ptl;
ptlCurrent = ptl;
ctlCurrent++;
}
/*
* Create a new report column
*/
VOID REPORT::Entry(COL col,SZ sz,CCH cch,SZ szTitle)
{
Assert(sz != szNil);
PEN pen = new EN;
/*
* Initialize the new Entry and then link with the rest..
*/
pen->penPrev = penCurrent;
pen->penNext = penNil;
pen->col = col;
pen->sz = sz;
pen->cch = cch;
pen->szTitle = szTitle;
/*
* Allow for creation of the first in the chain..
*/
if (penFirst == penNil)
penFirst = pen;
if (penCurrent != penNil)
penCurrent->penNext = pen;
/*
* Keep track of the maximum width..
*/
cchReportWidthMac = Max(cchReportWidthMac,col+cch);
penCurrent = pen;
}
/*
* Creates the report..
*/
VOID REPORT::Generate(BOOL fForward,BOOL fPrinter)
{
SZTEMP sz;
OUTPUT *popt;
BOOL (DATABASE:: *pfnInit)() = fForward ? DATABASE::FFirst : DATABASE::FLast;
BOOL (DATABASE:: *pfnTraverse)() = fForward ? DATABASE::FNext : DATABASE::FPrevious;
/*
* Create Title bar..
*/
CreateTitle(szTitleText,szTitleBar);
/*
* Creates and Initializes the output device.
*/
if (fPrinter)
popt = new PRINTER_OUTPUT(szTitleText,szTitleBar,ptlFirst,cchReportWidthMac);
else
popt = new SCREEN_OUTPUT(szTitleText,szTitleBar,ptlFirst,cchReportWidthMac,ctlCurrent);
/*
* Now, just traverse the database outputting each line
*/
Verify((rdtb.*pfnInit)());
do
{
/*
* Must check filter first..
*/
if (pfnFUsePdb == Nil || pfnFUsePdb(rdtb.PdbQuery()))
{
CreateOutput(sz);
popt->SendSz(sz);
}
}
while ((rdtb.*pfnTraverse)() && popt->FContinue());
/*
* Be sure to clean up our output device
*/
delete popt;
}
/*
* Creates the title bar and matching underline..
*/
VOID REPORT::CreateTitle(SZ szText,SZ szBar)
{
CCH cchMac = cchNil;
memset(szText,' ',cchSzTempMax);
memset(szBar,' ',cchSzTempMax);
for (PEN pen = penFirst; pen != penNil; pen = pen->penNext)
{
if (pen->sz != szNil)
{
strncpy(szText+pen->col,pen->szTitle,pen->cch);
memset(szBar+pen->col,'=',Max(pen->cch,strlen(pen->szTitle)));
}
if (pen->cch + pen->col > cchMac)
cchMac = pen->cch + pen->col;
}
OutputFix(szText,cchMac);
OutputFix(szBar,cchMac);
}
/*
* Output line. Called for each record..
*/
VOID REPORT::CreateOutput(SZ sz)
{
CCH cchMac = cchNil;
memset(sz,' ',cchSzTempMax);
/*
* Build output line..
*/
for (PEN pen = penFirst; pen != penNil; pen = pen->penNext)
{
strncpy(sz+pen->col,pen->sz,pen->cch);
if (pen->cch + pen->col > cchMac)
cchMac = pen->cch + pen->col;
}
OutputFix(sz,cchMac);
}
/*
* Removes any embedded \0 up to cchMac. Places \0 there
*/
VOID REPORT::OutputFix(SZ sz,CCH cchMac)
{
/*
* Place Nil at end..
*/
sz[cchMac] = chNil;
/*
* Assert that any \0s within the text are removed..
*/
for (CCH cch = cchNil; cch < cchMac; cch++)
{
if (sz[cch] == chNil)
sz[cch] = chSpace;
}
}
/*
* Report Implementations.
*/
OUTPUT::OUTPUT(SZ szText,SZ szBar,PTL ptl,CCH cchMac)
{
szTitleText = szText;
szTitleBar = szBar;
ptlFirst = ptl;
fContinueReport = fTrue;
cchReportWidthMac = cchMac;
}
/*
* Place holder for the destructor
*/
OUTPUT::~OUTPUT()
{
}
/*
* Answer if the report should be Continued..
*/
BOOL OUTPUT::FContinue()
{
return (fContinueReport);
}
/*
* Signals the termination of the report.
*/
VOID OUTPUT::Terminate()
{
fContinueReport = fFalse;
}
/*
* Report titles..
*/
VOID OUTPUT::Title()
{
PTL ptl = ptlFirst;
/*
* Output the title..
*/
while (ptl != ptlNil)
{
SZTEMP sz;
CCH cchLength = strlen(ptl->sz);
CCH cchOffset = cchNil;
/*
* Build the string/left/cented right
*/
memset(sz,' ',cchSzTempMax);
switch (ptl->al)
{
case alLeft:
cchOffset = cchNil;
break;
case alCentre:
cchOffset = (cchReportWidthMac >> 1) - (cchLength >> 1);
break;
case alRight:
cchOffset = cchReportWidthMac - cchLength;
break;
}
/*
* Now, pad the string with amount of spaces and output it..
*/
strcpy(sz+cchOffset,ptl->sz);
SendSz(sz);
ptl = ptl->ptlNext;
}
/*
* Output title/bar and reset cursor position
*/
SendSz(szTitleText);
SendSz(szTitleBar);
}
/*
* Screen output initialization. Opens the window and displays
* the first title/headings.
*/
SCREEN_OUTPUT::SCREEN_OUTPUT(SZ szText,SZ szBar,PTL ptl,CCH cchWidthMac,CTL ctl) : OUTPUT(szText,szBar,ptl,cchWidthMac)
{
crowMac = rowGlobalWindowBottom - 9 - ctl;
crowCurrent = rowNil;
wnd = WINDOW(4,3,rowGlobalWindowBottom-4,colGlobalWindowRight-3,coBlack,coCyan,szNil,fTrue);
/*
* Initialize window. Set scroll region so that title bar appears
* all the time..
*/
wnd.Open();
wnd.SetScrollRow(6+ctl,rowGlobalWindowBottom-4);
/*
* Output the title if any
*/
Title();
/*
* Since the TITLE is Fixed (I.e the window scrolls around it, reset
* the row counter here.
*/
crowCurrent = rowNil;
}
/*
* Remove the window..
*/
SCREEN_OUTPUT::~SCREEN_OUTPUT()
{
HELP hlp("Report finished, Press any key to continue");
(VOID)CdInput();
wnd.Close();
}
/*
* A single line of the report..
*/
VOID SCREEN_OUTPUT::SendSz(SZ sz)
{
/*
* Output the report line.
*/
wnd.Say(sz);
/*
* For output to the screen, give the users a screenful at a time
*/
if (++crowCurrent >= crowMac)
{
HELP hlp("Press ESC to Quit, any other key to continue");
if (CdInput() == cdEscape)
Terminate();
crowCurrent = rowNil;
}
/*
* If report is to continue, place the NL at the end
*/
if (FContinue())
wnd.PutCh(chReturn);
}
/*
* Printer initialization
*/
PRINTER_OUTPUT::PRINTER_OUTPUT(SZ szText,SZ szBar,PTL ptl,CCH cchWidthMac) : OUTPUT(szText,szBar,ptl,cchWidthMac)
{
crowMac = 60;
crowCurrent = rowNil;
/*
* Output the title if any
*/
Title();
}
/*
* Not much to do after the printer is finished
*/
PRINTER_OUTPUT::~PRINTER_OUTPUT()
{
}
/*
* Send a single line to the printer.
*/
VOID PRINTER_OUTPUT::SendSz(SZ sz)
{
fprintf(stdprn,"%s\n",sz);
if (++crowCurrent >= crowMac)
{
fprintf(stdprn,"\n\n\n\n\n\n");
fprintf(stdprn,"%s\n",szTitleText);
fprintf(stdprn,"%s\n",szTitleBar);
crowCurrent = 0;
}
}